/**
 * API错误处理Hook
 * 提供统一的错误处理和用户反馈机制
 */

import { useState, useCallback } from 'react'
import { useToast } from '@/hooks/use-toast'
import { ApiError } from '@/lib/types/api'

interface UseApiErrorOptions {
  showToast?: boolean      // 是否自动显示Toast提示
  autoRetry?: boolean      // 是否支持自动重试
  maxRetries?: number      // 最大重试次数
  retryDelay?: number      // 重试延迟(毫秒)
}

interface UseApiErrorReturn {
  error: ApiError | null
  isError: boolean
  clearError: () => void
  handleError: (error: any, failedAction?: () => Promise<any>) => void
  retry: () => void
  retryCount: number
  isRetrying: boolean
}

export function useApiError(options: UseApiErrorOptions = {}): UseApiErrorReturn {
  const {
    showToast = true,
    autoRetry = false,
    maxRetries = 3,
    retryDelay = 1000
  } = options

  const { toast } = useToast()
  const [error, setError] = useState<ApiError | null>(null)
  const [retryCount, setRetryCount] = useState(0)
  const [isRetrying, setIsRetrying] = useState(false)
  const [lastFailedAction, setLastFailedAction] = useState<(() => Promise<any>) | null>(null)

  const clearError = useCallback(() => {
    setError(null)
    setRetryCount(0)
    setLastFailedAction(null)
  }, [])

  const normalizeError = useCallback((error: any): ApiError => {
    // 如果已经是ApiError格式
    if (error && typeof error.code === 'number' && typeof error.message === 'string') {
      return error as ApiError
    }

    // 处理网络错误
    if (error instanceof TypeError && error.message.includes('fetch')) {
      return {
        code: 0,
        message: '网络连接失败，请检查网络设置',
        details: error
      }
    }

    // 处理超时错误
    if (error?.name === 'AbortError') {
      return {
        code: 408,
        message: '请求超时，请稍后重试',
        details: error
      }
    }

    // 处理从 HTTP 客户端抛出的错误（包含业务逻辑错误）
    if (error instanceof Error) {
      return {
        code: 500,
        message: error.message, // 直接使用错误消息，这里会包含服务器返回的 msg
        details: error
      }
    }

    // 处理一般错误
    return {
      code: error?.status || error?.code || 500,
      message: error?.message || error?.msg || '未知错误',
      details: error
    }
  }, [])

  const getErrorMessage = useCallback((error: ApiError): string => {
    // 优先检查是否有具体的业务错误消息
    if (error.message && error.message.trim()) {
      // 检查是否是来自服务器的业务逻辑错误消息，直接返回
      if (error.message.includes('已存在') || error.message.includes('不存在') || 
          error.message.includes('格式') || error.message.includes('密码') ||
          error.message.includes('用户名') || error.message.includes('邮箱') ||
          error.message.includes('重复') || error.message.includes('无效') ||
          error.message.includes('错误') || error.message.includes('失败')) {
        return error.message
      }
    }

    // 对于网络和系统错误，使用固定的友好提示
    switch (error.code) {
      case 0:
        return '网络连接异常，请检查网络设置'
      case 400:
        return error.message || '请求参数错误，请检查输入数据'
      case 401:
        return '认证失败，请重新登录'
      case 403:
        return '权限不足，无法访问该资源'
      case 404:
        return '请求的资源不存在'
      case 408:
        return '请求超时，请稍后重试'
      case 429:
        return '请求过于频繁，请稍后重试'
      case 500:
        return error.message || '服务器内部错误，请稍后重试'
      case 502:
        return '服务器网关错误，请稍后重试'
      case 503:
        return '服务暂时不可用，请稍后重试'
      default:
        return error.message || '操作失败，请重试'
    }
  }, [])

  const shouldAutoRetry = useCallback((error: ApiError): boolean => {
    if (!autoRetry || retryCount >= maxRetries) {
      return false
    }

    // 网络错误、超时错误、服务器错误可以重试
    const retryableCodes = [0, 408, 429, 500, 502, 503]
    return retryableCodes.includes(error.code)
  }, [autoRetry, retryCount, maxRetries])

  const retry = useCallback(async () => {
    if (!lastFailedAction || isRetrying) {
      return
    }

    setIsRetrying(true)
    setRetryCount(prev => prev + 1)

    try {
      await new Promise(resolve => setTimeout(resolve, retryDelay))
      await lastFailedAction()
      clearError() // 重试成功，清除错误
    } catch (error) {
      handleError(error, lastFailedAction) // 重试失败，继续处理错误
    } finally {
      setIsRetrying(false)
    }
  }, [lastFailedAction, isRetrying, retryDelay, clearError])

  const handleError = useCallback((error: any, failedAction?: () => Promise<any>) => {
    const normalizedError = normalizeError(error)
    setError(normalizedError)

    if (failedAction) {
      setLastFailedAction(() => failedAction)
    }

    // 显示Toast提示
    if (showToast) {
      const message = getErrorMessage(normalizedError)
      toast({
        title: '操作失败',
        description: message,
        variant: 'destructive',
        duration: 5000,
      })
    }

    // 自动重试逻辑
    if (shouldAutoRetry(normalizedError) && failedAction) {
      setTimeout(() => {
        retry()
      }, retryDelay)
    }

    console.error('API错误:', normalizedError)
  }, [normalizeError, showToast, getErrorMessage, shouldAutoRetry, retry, retryDelay, toast])

  return {
    error,
    isError: error !== null,
    clearError,
    handleError,
    retry,
    retryCount,
    isRetrying,
  }
}

/**
 * 包装异步函数，自动处理错误
 */
export function useApiCall<T extends any[], R>(
  apiFunction: (...args: T) => Promise<R>,
  options: UseApiErrorOptions = {}
) {
  const { handleError, clearError, ...errorState } = useApiError(options)
  const [isLoading, setIsLoading] = useState(false)
  const [data, setData] = useState<R | null>(null)

  const execute = useCallback(async (...args: T): Promise<R | null> => {
    setIsLoading(true)
    clearError()

    try {
      const result = await apiFunction(...args)
      setData(result)
      return result
    } catch (error) {
      handleError(error, async () => {
        const result = await apiFunction(...args)
        setData(result)
        return result
      })
      return null
    } finally {
      setIsLoading(false)
    }
  }, [apiFunction, handleError, clearError])

  return {
    execute,
    data,
    isLoading,
    ...errorState,
  }
}